Skip to content

Add AWS STS authentication tutorial and cross-references#550

Open
jhrozek wants to merge 1 commit intomainfrom
aws_sts
Open

Add AWS STS authentication tutorial and cross-references#550
jhrozek wants to merge 1 commit intomainfrom
aws_sts

Conversation

@jhrozek
Copy link
Contributor

@jhrozek jhrozek commented Feb 13, 2026

Description

Tutorial covering end-to-end setup of ToolHive as an authentication proxy for the AWS MCP Server on Kubernetes. Users register their OIDC provider with AWS IAM, create IAM roles with the aws-mcp permission model, configure MCPExternalAuthConfig with type: awsSts, and deploy an MCPRemoteProxy pointing to the AWS MCP Server endpoint.

Type of change

  • New documentation

Related issues/PRs

#510

Screenshots

N/A

Submitter checklist

Content and formatting

  • I have reviewed the content for technical accuracy
  • I have reviewed the content for spelling, grammar, and style

Navigation

  • New pages include a frontmatter section with title and description at a minimum
  • Sidebar navigation (sidebars.ts) updated for added, deleted, reordered, or renamed files
  • Redirects added to vercel.json for moved, renamed, or deleted pages (i.e., if the URL slug changed)

Reviewer checklist

Content

  • I have reviewed the content for technical accuracy
  • I have reviewed the content for spelling, grammar, and style

Tutorial covering end-to-end setup of ToolHive as an authentication
proxy for the AWS MCP Server on Kubernetes. Users register their
OIDC provider with AWS IAM, create IAM roles with the aws-mcp
permission model, configure MCPExternalAuthConfig with type: awsSts,
and deploy an MCPRemoteProxy pointing to the AWS MCP Server endpoint.

Also adds cross-references from existing token exchange and remote
proxy docs so readers discover the AWS-specific auth path:

- concepts/backend-auth: mention AWS STS in the federation section,
  add "Built-in AWS STS support" subsection
- guides-k8s/token-exchange-k8s: link in Related information
- guides-k8s/remote-mcp-proxy: tip admonition after token exchange
  section

Fixes: #510
Copilot AI review requested due to automatic review settings February 13, 2026 15:18
@vercel
Copy link

vercel bot commented Feb 13, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs-website Ready Ready Preview, Comment Feb 13, 2026 3:21pm

Request Review

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds new ToolHive documentation describing how to use AWS STS (via OIDC) to authenticate to the AWS MCP Server, and links to this new tutorial from existing Kubernetes/token-exchange documentation and the sidebar navigation.

Changes:

  • Added a new end-to-end tutorial for AWS STS authentication to the AWS MCP Server on Kubernetes.
  • Updated Docusaurus sidebar to include the new tutorial.
  • Added cross-references/tips in existing token exchange, remote proxy, and backend-auth concept docs.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
sidebars.ts Adds the new AWS STS tutorial to the Tutorials sidebar navigation.
docs/toolhive/tutorials/aws-sts-integration.mdx New tutorial covering AWS IAM OIDC provider setup, role/policy examples, and ToolHive resources for AWS STS-based auth.
docs/toolhive/guides-k8s/token-exchange-k8s.mdx Links token exchange guide readers to the AWS STS tutorial.
docs/toolhive/guides-k8s/remote-mcp-proxy.mdx Adds a tip steering AWS users toward type: awsSts and the new tutorial.
docs/toolhive/concepts/backend-auth.mdx Adds conceptual mention of built-in AWS STS support and links to the tutorial.

Comment on lines +150 to +151
"Federated": "arn:aws:iam::<YOUR_AWS_ACCOUNT_ID>:oidc-provider/<YOUR_OIDC_ISSUER_HOST>"
},
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The OIDC provider ARN placeholder <YOUR_OIDC_ISSUER_HOST> is likely misleading for issuers that include a path (common with Okta/Keycloak). In AWS, the oidc-provider/... segment must match the provider URL without the scheme and including any path; consider renaming the placeholder and clarifying this here.

Copilot uses AI. Check for mistakes.
Comment on lines +270 to +273
spec:
type: awsSts
awsSts:
region: <YOUR_AWS_REGION>
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docs now instruct users to set spec.type: awsSts with an awsSts: block, but the current CRD reference lists MCPExternalAuthConfigSpec.type enum values without awsSts and doesn’t document an awsSts field (see docs/toolhive/reference/crd-spec.md around the MCPExternalAuthConfigSpec table). Either update the CRD reference (and ensure the operator actually supports awsSts), or gate this tutorial behind the ToolHive version that introduces it.

Copilot uses AI. Check for mistakes.
Comment on lines +436 to +438
For AWS services like the AWS MCP Server, use `type: awsSts` instead of
`type: tokenExchange`. This exchanges OIDC tokens for temporary AWS credentials
via `AssumeRoleWithWebIdentity` and signs requests with SigV4. See the
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This tip suggests switching MCPExternalAuthConfig.spec.type to awsSts, but the CRD reference currently doesn’t list awsSts as a supported enum value for MCPExternalAuthConfigSpec.type. Either update the reference/CRD docs alongside this change or add an explicit minimum ToolHive version requirement.

Suggested change
For AWS services like the AWS MCP Server, use `type: awsSts` instead of
`type: tokenExchange`. This exchanges OIDC tokens for temporary AWS credentials
via `AssumeRoleWithWebIdentity` and signs requests with SigV4. See the
In ToolHive installations where `MCPExternalAuthConfig.spec.type` supports the
`awsSts` mode (check your installed CRD or reference docs), you can use
`type: awsSts` instead of `type: tokenExchange` for AWS services like the AWS
MCP Server. This exchanges OIDC tokens for temporary AWS credentials via
`AssumeRoleWithWebIdentity` and signs requests with SigV4. See the

Copilot uses AI. Check for mistakes.
Comment on lines +89 to +93
```bash
aws iam create-open-id-connect-provider \
--url https://<YOUR_OIDC_ISSUER> \
--client-id-list <YOUR_OIDC_AUDIENCE>
```
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aws iam create-open-id-connect-provider typically requires --thumbprint-list, and the placeholder usage is inconsistent: the command hard-codes https:// but the <YOUR_OIDC_ISSUER> example below includes https://..., which would lead to a doubled scheme if copied literally. Update the command/placeholders to be unambiguous and include the required thumbprint input.

Copilot uses AI. Check for mistakes.
Comment on lines +154 to +156
"StringEquals": {
"<YOUR_OIDC_ISSUER_HOST>:aud": "<YOUR_OIDC_AUDIENCE>"
}
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, the IAM trust policy condition key should match the full OIDC provider identifier (host plus any issuer path) used when creating the provider (for example issuer.example.com/oauth2/default:aud). Clarify that <...>:aud must include the same path portion if present.

Copilot uses AI. Check for mistakes.
--auth-method client_secret_basic \
--response-mode form_post \
--response-types code \
--pkce | jq -r '.access_token')
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example pipes oauth2c output through jq, but the tutorial doesn’t mention jq as a prerequisite. Add it to prerequisites or show an alternative that doesn’t require jq.

Copilot uses AI. Check for mistakes.
Comment on lines +265 to +266
services, ToolHive has built-in STS support using `MCPExternalAuthConfig` with
`type: awsSts`
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This guide recommends type: awsSts, but the CRD reference currently doesn’t list awsSts as a valid MCPExternalAuthConfigSpec.type value. Please update the CRD reference (or adjust the guidance) so readers don’t end up with manifests rejected by the API server.

Suggested change
services, ToolHive has built-in STS support using `MCPExternalAuthConfig` with
`type: awsSts`
services, ToolHive has built-in STS support; see this tutorial and the
MCPExternalAuthConfig CRD reference for the correct configuration

Copilot uses AI. Check for mistakes.
Comment on lines +310 to +319
### Built-in AWS STS support

For AWS services like the
[AWS MCP Server](https://docs.aws.amazon.com/aws-mcp/), ToolHive has built-in
support for exchanging OIDC tokens for temporary AWS credentials using
`AssumeRoleWithWebIdentity`. This handles the STS exchange and SigV4 request
signing automatically, with claim-based IAM role selection. See the
[AWS STS integration tutorial](../tutorials/aws-sts-integration.mdx) for a
step-by-step setup guide.

Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section claims built-in AWS STS support, but the current CRD spec documentation for MCPExternalAuthConfig doesn’t include an awsSts type/config. Please align this concept doc with the actual shipped CRD (or update the CRD reference docs in the same change) to avoid documenting unsupported configuration.

Suggested change
### Built-in AWS STS support
For AWS services like the
[AWS MCP Server](https://docs.aws.amazon.com/aws-mcp/), ToolHive has built-in
support for exchanging OIDC tokens for temporary AWS credentials using
`AssumeRoleWithWebIdentity`. This handles the STS exchange and SigV4 request
signing automatically, with claim-based IAM role selection. See the
[AWS STS integration tutorial](../tutorials/aws-sts-integration.mdx) for a
step-by-step setup guide.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this (and other similar comments from Copilot) are because a release hasn't been cut with these new fields yet? That will auto-update the CRD reference.

[Kubernetes quickstart guide](./quickstart-k8s.mdx))
- `kubectl` configured to access your cluster
- An AWS account with permissions to create IAM roles, policies, and OIDC
identity providers
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tutorial uses aws CLI commands later, but the prerequisites don’t mention installing/configuring the AWS CLI (and credentials for running IAM commands). Add AWS CLI as an explicit prerequisite so readers can follow Step 1/2 without getting blocked.

Suggested change
identity providers
identity providers
- The AWS CLI installed and configured with IAM credentials that can create
IAM roles, policies, and OIDC identity providers

Copilot uses AI. Check for mistakes.
Copy link
Collaborator

@danbarr danbarr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks really great! I have some small nits and one thing that a Claude review pointed out which may or may not be an issue.

Comment on lines +247 to +257
:::info[How role selection works]

When a request arrives, ToolHive evaluates your role mappings in priority order
(lower number = higher priority). The first matching rule determines which IAM
role to assume. If no mapping matches, the fallback role is used.

For example, if a user belongs to both `s3-readers` and `developers` groups, and
`s3-readers` has a lower priority number, ToolHive selects the S3 read-only
role.

:::
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This note feels too early, priority doesn't appear until the next section, suggest moving it down to line 291, just after the placeholders but before applying it.

Create an `MCPExternalAuthConfig` resource that defines how ToolHive exchanges
OIDC tokens for AWS credentials.

```yaml {4,7,10,13-17} title="aws-sts-auth-config.yaml"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The line highlighting seems off here. The name (since it's referenced later) and type make sense, but guessing the highlight on the blank line is just a one-off miss? In fact since most of it is directly relevant, maybe just highlight the type field? Optionally could also highlight the three lines with placeholders to replace (9,13,19) but that makes it a little staccato to read.

Suggested change
```yaml {4,7,10,13-17} title="aws-sts-auth-config.yaml"
```yaml {4,7} title="aws-sts-auth-config.yaml"

Comment on lines +355 to +356
Replace the placeholders with your OIDC provider's configuration. Update the
region in `remoteURL` if you're not using `us-east-1`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From their docs, I believe the MCP itself only exists in us-east-1, and the region for operations is influenced by a flag on their own proxy wrapper for it, or by the prompt that invokes the tools? I get an NXDOMAIN when I try to resolve the MCP endpoint on any region other than us-east-1.

Comment on lines +377 to +378
To make the proxy accessible to clients outside the cluster, create Gateway and
HTTPRoute resources:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth calling out that this assumes the reader is using a GatewayAPI solution and it would need adjustment for Ingress controllers?

Comment on lines +427 to +429
For detailed guidance on setting up ingress, including ngrok for development,
see
[Configure secure ingress for MCP servers on Kubernetes](./k8s-ingress-ngrok.mdx).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 to calling out the specific ngrok guide, we also have the more generic "Connect clients to MCP servers" guide too (../guides-k8s/connect-clients.mdx)

kubectl delete httproute aws-mcp-route -n toolhive-system
```

Optionally, remove the AWS IAM resources:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're cleaning up, let's clean up 😄

Suggested change
Optionally, remove the AWS IAM resources:
Remove the AWS IAM resources:

Comment on lines +129 to +130
- `CallReadOnlyTool` - search documentation, list regions, get CLI suggestions
(7 of 9 tools)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: the "7 of 9 tools" will go stale, maybe not necessary at all or replace with "most tools"?


:::info[What's happening?]

The `roleMappings` field uses simple claim matching by default: if the value in
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The explanation here references "the roleClaim JWT claim (here, groups)" but the YAML in Step 3 doesn't include a roleClaim field anywhere. The YAML shows claim: s3-readers under roleMappings, where a reader would naturally parse claim as a claim name rather than a value to match against.

Three things need clarifying:

  1. Where does groups come from? If roleClaim is a CRD field that defaults to groups, mention that explicitly — even a YAML comment like # roleClaim defaults to "groups" in the example would help.
  2. The claim field under roleMappings represents a value to match, not a claim name — that's counterintuitive and worth a sentence of explanation.
  3. Readers whose IdP uses a different claim name (e.g., Auth0 may use roles or a custom namespace instead of groups) need to know how to change it.

Without this, a reader who doesn't happen to have a groups claim in their tokens won't know what to adjust.


Generated by Claude Code

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude identified this; I'm not as well-versed in the specifics here so take it with a grain of salt 😉

'toolhive/tutorials/mcp-optimizer',
'toolhive/tutorials/custom-registry',
'toolhive/tutorials/vault-integration',
'toolhive/tutorials/aws-sts-integration',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Phase 1 of the restructuring was just merged, so you'll need to rebase to put this in the new integrations sidebar section. The actual file location is fine, those won't move until phase 2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants